Decorator for user verificationΒΆ

The user should be an instance of User or AnonymousUser class.
Notes:
1. Consider a method that is expected to take a user as its first argument.
2. This decorator will only correctly wrap a function or static method,
and will fail if wrapping a bound method to a class.
This is because the decorator ignores the expectation to send self
as the first argument to a bound method.
import functools

class User(object):
    """A representation of a logged in user"""
    def __init__(self, username, email):
        self.username = username
        self.email = email

class AnonymousUser(object):
    """An anonymous user; a stand-in for an actual user
       that nonetheless is not an actual user
    """
    def __init__(self):
        self.username = None
        self.email = None

def requires_user(func):
    # Preserving the help of the inner function
    @functools.wraps(func)
    def inner(user, *args, **kwargs):
        """Verify that the user is truthy; if so, run the decorated method,
           and if not, raise ValueError.
        """
        # Ensure that user is truthy, and of the correct type.
        # The "truthy" check will fail on anonymous users, since the
        # AnonymousUser subclass has a `__nonzero__` method that
        # returns False.
        if user and isinstance(user, User):
            return func(user, *args, **kwargs)
        else:
            raise ValueError('A valid user is required to run this method')
    return inner

u1 = User('john', 'jmarlett@gmail.com')
u2 = AnonymousUser()

def func_01(user, x=3):
    return x

@requires_user
def func_02(user, x=5):
    return x

print(func_01(u1))      # 3
print(func_02(u1))      # 5
print(func_01(u2))      # 3
# print(func_02(u2))
# ValueError: A valid user is required to run this method